/*
 * Sensor.cpp
 *
 *  Created on: Mar 2, 2012
 *      Author: Zon
 */

#include "BaseStation.h"
#include "Sensor.h"

Define_Module(BaseStation);

void BaseStation::initialize() {
    this->xpos = par("xpos");
    this->ypos = par("ypos");
    this->sensorRange = getParentModule()->par("sensorRangeWSN");
    this->numberData = 0;
    this->currRound = 0;
    this->protocol = getParentModule()->par("protocol");
    this->finalRound = getParentModule()->par("finalRound");
    this->eventId = 0;
    this->numberDataMax = 0;
    this->numberData = 0;
    this->numberNode = getParentModule()->par("numNodes");
    this->totalDataPacket = 0;
    this->totalLoss = 0;
    this->numberErrorMessage = 0;
    this->numberSuccessPacket2 = 0;
    this->totalSuccessPacket2 = 0;
    WATCH(currRound);
    WATCH(numberDataMax);
    WATCH(numberErrorMessage);
    WATCH(numberNode);
    WATCH(numberSuccessPacket2);
    cMessage *cmsg = new cMessage();
    cmsg->setKind(SMSG_INIT);
    scheduleAt(simTime() + 2, cmsg);
}
void BaseStation::endRound() {
    Enter_Method_Silent("endRound");
    ev << "vao day2 \n";
    if (numberData < numberDataMax) {
        ev << "BS Nhan dc data " << numberData << "/" << numberDataMax << "\n";
    } else {
        ev << "BS Nhan dc data " << numberData << "/" << numberDataMax << "\n";
        ev << "Thuc hien reset round \n";
        //Xac dinh so nut chet trong round do
        int numberAliveNode = 0;
        long totalEnergy = 0;
        for (int i = 2; i < simulation.getLastModuleId(); i++) {
            Sensor *sensor = check_and_cast<Sensor*>(simulation.getModule(i));
            if (sensor->status != STT_IS_DEATH) {
                if (sensor->energy < sensor->energyMax / 10) {
                    sensor->energy = 0;
                    sensor->status = STT_IS_DEATH;
                    ev << "Xet death node tai " << sensor->getId() << "\n";
                    cDisplayString& connDispStr = sensor->getDisplayString();
                    connDispStr.parse("i=misc/node,pink;is=vs");
                } else {
                    totalEnergy += sensor->energy;
                    numberAliveNode++;
                }
            } else {

            }
            //recordScalar("E res", sensor->energy);
        }

        totalLoss += numberErrorMessage;
        totalDataPacket += numberDataMax;
        totalSuccessPacket2 += numberSuccessPacket2;
        double errorRate = numberErrorMessage * 1.0 / numberDataMax * 100;
        recordScalar("Packet Loss", numberErrorMessage);
        recordScalar("Total Packet", numberDataMax);
        recordScalar("Packet Success", numberSuccessPacket2);
        recordScalar("AliveNode", numberAliveNode);
        recordScalar("TotalEn", totalEnergy);

        currRound++;
        numberData = 0;
        numberErrorMessage = 0;
        numberSuccessPacket2 = 0;
        numberDataMax = 0;
        //if (numberAliveNode<2*200/3)
        if (currRound == finalRound) {
            //  if (numberAliveNode<2*200/3) {
            recordScalar("Final Round", currRound - 1);
            recordScalar("Total Loss", totalLoss);
            recordScalar("Total Data pakcet", totalDataPacket);
            recordScalar("Total Success", totalSuccessPacket2);
            ev << "End at round " << currRound - 1 << "\n";
            endSimulation();
        }
        eventId = 0;

        //Thuc hien reset cac nut
        for (int i = 2; i < simulation.getLastModuleId(); i++) {
            Sensor *sensor = check_and_cast<Sensor*>(simulation.getModule(i));
            sensor->resetRound();
        }

        simulation.msgQueue.clear();
        totalCH = 0;
        ev << "Start Round "<<currRound<<" at Event" << simulation.getEventNumber() << " \n";
        do {
            for (int i = 2; i < simulation.getLastModuleId(); i++) {
                Sensor *sensor = check_and_cast<Sensor*>(
                        simulation.getModule(i));
                sensor->generateEvent();
            }
            if (totalCH == 0) {
                currRound++;
                ev << "Khong co CH thoa man dieu kien xac suat \n";
            }
        } while (totalCH == 0);



    }

}

void BaseStation::handleMessage(cMessage *msg) {
    ev << "Base event, messKind =" << msg->getKind() << "\n";
    if (msg->isSelfMessage()) {
        ev << "BaseStation " << this->getId() << " got self message type: "
                << msg->getKind() << "\n";
        if (msg->getKind() == SMSG_INIT) {
            ev << "BaseStation got start message \n";
            //Khoi tao link giua BS voi tat ca cac nut trong mang
            initBaseStaion();
        }
    } else {
        //Cho numberData tang len tai CH root
        //numberData++;
        int messKind = msg->getKind();
        ev << "vao day \n";
        if (messKind == MSG_DATA2RN) {
            numberSuccessPacket2++;
        }

    }
    delete (msg);
}

void BaseStation::initBaseStaion() {
    cModule *parent = this->getParentModule();
    cModule *mod;
    int numNodes;

    numNodes = (int) parent->par("numNodes");

    for (int i = 2; i < simulation.getLastModuleId(); i++) {

        //khoi tao gateTool cho tung nut mang

        mod = (cModule *) simulation.getModule(i);
        char idStr[15];
        sprintf(idStr, "%d to %d ", this->getId(), i);

        char gateName[5] = "link";
        char *temp = strcat(gateName, idStr);
        cGate *ownGate = addGate(temp, cGate::OUTPUT);

        cGate *otherGate = mod->addGate(temp, cGate::INPUT);
        ownGate->connectTo(otherGate);
        //hide link arow

        cDisplayString& connDispStr = ownGate->getDisplayString();
        connDispStr.parse("ls=,0");

        //hide link arrow in each Sensor

    }

}

double BaseStation::distanceCal(int x1, int y1, int x2, int y2) {
    double distance;
    distance = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    return distance;

}

